package com.yuncheng.spcyApi.spcy;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yuncheng.spcyApi.alog.annotation.Log;
import com.yuncheng.spcyApi.constant.common.LogConstant;
import com.yuncheng.spcyApi.constant.common.SpcyConstant;
import com.yuncheng.exception.BusinessException;
import com.yuncheng.spcyApi.service.ISpcyFgbzkTypeService;
import com.yuncheng.spcyApi.service.ISpcyLogService;
import com.yuncheng.spcyApi.utils.DateConvert;
import com.yuncheng.spcyApi.utils.GetUuIdUtils;
import com.yuncheng.vo.HttpResult;
import com.yuncheng.spcyApi.entity.SpcyFgbzkType;
import com.yuncheng.spcyApi.vo.common.FgbzkTreeVo;
import com.yuncheng.spcyApi.vo.common.TreeTwoVo;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import utils.LogUtils;
import utils.ObjectToMapUtils;

@Api(tags = "审评查验-法规标准库-类型接口")
@RestController
@RequestMapping("/api/spzx-spcy/fgbzkType")
public class SpcyFgbzkTypeController  {

    private static final Logger log = LoggerFactory.getLogger(SpcyFgbzkTypeController.class);

    @Resource
    private ISpcyFgbzkTypeService spcyFgbzkTypeService;

    @Resource
    private ISpcyLogService spcyLogService;

    @Log(title = "法规标准库-类型-管理查询")
    @ApiOperation(value = "法规标准库-类型-管理查询")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "flxmc",value = "类型名称")
    })
    @GetMapping(value = "/queryTreeList")
    public HttpResult<?> queryTreeList(@RequestParam(value = "flxmc",defaultValue = "") String flxmc) {
        List<FgbzkTreeVo> ZltxwjTreeVos = spcyFgbzkTypeService.selectAllType("");

        List<FgbzkTreeVo> ZltxwjTreeVos1 = this.delJd(ZltxwjTreeVos, flxmc);
        return HttpResult.ok(ZltxwjTreeVos1);
    }

    @Log(title = "法规标准库-类型-数组查询")
    @ApiOperation(value = "法规标准库-类型-数组查询")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "flxmc",value = "类型名称")
    })
    @GetMapping(value = "/queryPageList")
    public HttpResult<?> queryPageList(@RequestParam(value = "flxmc",defaultValue = "") String flxmc) {
        List<SpcyFgbzkType> list = spcyFgbzkTypeService.list(new LambdaQueryWrapper<SpcyFgbzkType>()
                .eq(StringUtils.isNotBlank(flxmc), SpcyFgbzkType::getFlxmc, flxmc)
                .orderByAsc(SpcyFgbzkType::getForder));
        return HttpResult.ok(list);
    }

    @Log(title = "法规标准库-类型-树形结构查询")
    @ApiOperation(value = "法规标准库-类型-树形结构查询")
    @GetMapping(value = "getTreeTypeList")
    public HttpResult<?> getTreeTypeList(){
        List<FgbzkTreeVo> ZltxwjTreeVos = spcyFgbzkTypeService.selectAllType(null);

        List<TreeTwoVo> treeList = new ArrayList<>();
        for (FgbzkTreeVo type : ZltxwjTreeVos){
            TreeTwoVo treeVo = new TreeTwoVo();
            treeVo.setKey(type.getId());
            treeVo.setValue(type.getFlxmc());
            treeVo.setChildren(this.getTreeList(type.getChildren()));
            treeList.add(treeVo);
        }

        return HttpResult.ok(treeList);
    }

    /**
     * 递归-将树形数据组成treeVo结构数据
     * @param ZltxwjTreeVoList
     * @return
     */
    public List<TreeTwoVo> getTreeList(List<FgbzkTreeVo> ZltxwjTreeVoList){
        List<TreeTwoVo> treeList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(ZltxwjTreeVoList)){
            for (FgbzkTreeVo type : ZltxwjTreeVoList){
                TreeTwoVo treeVo = new TreeTwoVo();
                treeVo.setKey(type.getId());
                treeVo.setValue(type.getFlxmc());
                treeVo.setChildren(this.getTreeList(type.getChildren()));
                treeList.add(treeVo);
            }
        }
        return treeList;
    }

    /**
     * 递归-根据类型名称-重新组成新的treeVo结构数据
     * @param ZltxwjTreeVoList
     * @param flxmc
     * @return
     */
    public List<FgbzkTreeVo> delJd(List<FgbzkTreeVo> ZltxwjTreeVoList, String flxmc){
        if (CollectionUtils.isNotEmpty(ZltxwjTreeVoList) && StringUtils.isNotBlank(flxmc)) {
            for (FgbzkTreeVo treeVo : ZltxwjTreeVoList) {
                if (CollectionUtils.isNotEmpty(treeVo.getChildren())) {
                    treeVo.setChildren(this.delJd(treeVo.getChildren(), flxmc));
                    if (CollectionUtils.isEmpty(treeVo.getChildren())) {
                        if (StringUtils.isNotBlank(flxmc) && !treeVo.getFlxmc().contains(flxmc)) {
                            ZltxwjTreeVoList.remove(treeVo);
                            return this.delJd(ZltxwjTreeVoList, flxmc);
                        }
                    }
                } else {
                    if (StringUtils.isNotBlank(flxmc) && !treeVo.getFlxmc().contains(flxmc)) {
                        ZltxwjTreeVoList.remove(treeVo);
                        return this.delJd(ZltxwjTreeVoList, flxmc);
                    }
                }
            }
        }

        return ZltxwjTreeVoList;
    }

    @Log(title = "法规标准库-类型-添加")
    @ApiOperation(value = "法规标准库-类型-添加")
    @PostMapping(value = "/addType")
    public HttpResult<?> addType(@RequestBody SpcyFgbzkType spcyFgbzkType) {
        if (StringUtils.isBlank(spcyFgbzkType.getFlxmc())){
            return HttpResult.error("请类型名称不能为空，请输入!");
        }
        spcyFgbzkType.setId(GetUuIdUtils.ReplaceUuId());
        boolean parentOrder = true; // 是否为父级，默认是
        if (StringUtils.isNotBlank(spcyFgbzkType.getFparentid())){
            parentOrder = false;
        }

        // 排序为空时，父级自动排序
        if (spcyFgbzkType.getForder() == null && parentOrder){
            List<SpcyFgbzkType> parentList = spcyFgbzkTypeService.list(new LambdaQueryWrapper<SpcyFgbzkType>()
                    .isNull(SpcyFgbzkType::getFparentid));
            int count = parentList.size() + 1;
            spcyFgbzkType.setForder(count);
        }

        // 排序为空时，子级自动排序
        if (spcyFgbzkType.getForder() == null && !parentOrder){
            List<SpcyFgbzkType> childList = spcyFgbzkTypeService.list(new LambdaQueryWrapper<SpcyFgbzkType>()
                    .isNotNull(SpcyFgbzkType::getFparentid)
                    .eq(SpcyFgbzkType::getFparentid, spcyFgbzkType.getFparentid()));
            int count = childList.size() + 1;
            spcyFgbzkType.setForder(count);
        }

        boolean save = spcyFgbzkTypeService.save(spcyFgbzkType);
        if (!save){
            return HttpResult.error("保存失败，请联系管理员，并刷新重试");
        }
        String log = "新增法规标准库类型：";
        Map<String, Object> logMap = ObjectToMapUtils.objectToMap(spcyFgbzkType);
        log += LogUtils.MapToStringMethod(logMap);
        spcyLogService.addLogs(LogConstant.LOGS_FGBZK,log,spcyFgbzkType.getId(), SpcyConstant.LOGS_SYS_TYPE_XZ,SpcyConstant.LOGS_SYS_TYPE_XZ);

        return HttpResult.ok("保存成功");
    }

    @Log(title = "法规标准库-类型-编辑")
    @ApiOperation(value = "法规标准库-类型-编辑")
    @PutMapping(value = "/editType")
    public HttpResult<?> editType(@RequestBody SpcyFgbzkType spcyFgbzkType) {
        SpcyFgbzkType typeUpdate = spcyFgbzkTypeService.getById(spcyFgbzkType.getId());
        if (typeUpdate == null){
            return HttpResult.error("当前分类不存在，请刷新重试");
        }
        Map<String, Object> oldMap = ObjectToMapUtils.objectToMap(typeUpdate);
        ConvertUtils.register(new DateConvert(), java.util.Date.class);
        // 自动完成页面到bean的数据对接
        try {
            BeanUtils.populate(typeUpdate, BeanUtils.describe(spcyFgbzkType));
        } catch (IllegalAccessException e) {
            log.error("法规标准库-类型-编辑更新失败[IllegalAccessException]: {}",e.getMessage());
        } catch (InvocationTargetException e) {
            log.error("质法规标准库-类型-编辑更新失败[InvocationTargetException]: {}",e.getMessage());
        } catch (NoSuchMethodException e) {
            log.error("法规标准库-类型-编辑更新失败[]: {NoSuchMethodException}",e.getMessage());
        }
        boolean flag = spcyFgbzkTypeService.updateById(typeUpdate);
        if (!flag){
            return HttpResult.error("保存失败,请联系管理员,并刷新重试");
        }
        String operContent = "基本信息修改：";
        operContent += LogUtils.BeanModifyMsg(typeUpdate, oldMap);

        spcyLogService.addLogs(LogConstant.LOGS_FGBZK, operContent, typeUpdate.getId(), SpcyConstant.LOGS_SYS_TYPE_XG, SpcyConstant.LOGS_SYS_TYPE_XG);


        return HttpResult.ok("保存成功");
    }


    @Log(title = "法规标准库-类型-删除")
    @ApiOperation(value = "法规标准库-类型-删除")
    @DeleteMapping(value = "/deleteType")
    public HttpResult<?> deleteType(@RequestParam("id") String id) {
        if (StringUtils.isBlank(id)){
            return HttpResult.error("参数丢失，请联系管理员");
        }
        String log = "";

        SpcyFgbzkType type = spcyFgbzkTypeService.getById(id);
        if (type == null){
            return HttpResult.error("当前类型不存在，请刷新重试");
        }

        // 是否存在子级
        List<String> childList = spcyFgbzkTypeService.selectChildTypeListById(id);
        if (CollectionUtils.isNotEmpty(childList)){
            return HttpResult.error("当前【"+type.getFlxmc()+"】下存在子级，无法删除，请先删除子级。");
        }

        List<String> list = spcyFgbzkTypeService.selectZltxwjByTypeId(id);
        if (CollectionUtils.isNotEmpty(list)){
            throw new BusinessException("改类型下存在对应的法规标准库无法删除改类型！");
        }

        boolean delFlag = spcyFgbzkTypeService.removeById(id);
        if (!delFlag){
            return HttpResult.error("删除失败，请联系管理员,并刷新重试");
        }
        log = "删除法规标准库类型: ";
        Map<String, Object> logMap = ObjectToMapUtils.objectToMap(type);
        log += LogUtils.MapToStringMethod(logMap);
        spcyLogService.addLogs(LogConstant.LOGS_FGBZK,log,id, SpcyConstant.LOGS_SYS_TYPE_SC,SpcyConstant.LOGS_SYS_TYPE_SC);

        return HttpResult.ok("删除成功");
    }


    @Log(title = "法规标准库-类型-通过id查询")
    @ApiOperation(value = "法规标准库-类型-通过id查询")
    @GetMapping(value = "/queryById")
    public HttpResult<?> queryById(@RequestParam("id") String id) {
        SpcyFgbzkType SpcyFgbzkType = spcyFgbzkTypeService.getById(id);
        return HttpResult.ok(SpcyFgbzkType);
    }

}
